﻿#include "CenterRoomModule.h"
#include "base/core/com_define.h"
#include "base/net/net_pack_handle.h"
#include "Common/ServerDefine.h"
#include "../CenterService.h"
#include "../Active/ActiveCharacterMgr.h"
#include "../Cache/OfflineCharacterDataMgr.h"
#include "ChatCenter/ChatCenter.h"
#include "Room/RoomMgr.h"
#include "Common/TableData/DuplicateDuplicateCfg.h"
#include "Common/TableData/DuplicateGroupCfg.h"
#include "RelationMgr/RelationMgr.h"

#ifdef _MSC_VER
#pragma warning(disable:4100)
#endif
#include "ProtoBuffer/AllProtocol.h"


using namespace ProtoBuf;


CenterRoomModule::CenterRoomModule()
{

}

CenterRoomModule::~CenterRoomModule()
{

}


bool CenterRoomModule::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	pMessageDispatch->registerServerHandler(EMODULE_ID_ROOM, this);

	return true;
}

void CenterRoomModule::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return;
	}
	pMessageDispatch->unregisterServerHandler(EMODULE_ID_ROOM);
}

void CenterRoomModule::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case LOGIC_TO_CENTER_ROOM_LIST: //房间列表
	{
		RoomList(package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_CREATE: //创建房间
	{
		CreateRoom(package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_SET_PWD: //设置密码
	{
		SetRoomPwd( package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_JOIN:			//加入房间
	{
		JoinRoom(package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_INVITE_FRIEND:	//邀请好友
	{
		InviteFriend( package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_INVITE_REPLY:	//回复邀请
	{
		ReplyInvite(package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_KICK:	//请离房间
	{
		KickRoom( package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_LEAVE:	//离开房间
	{
		LeaveRoom(package);
	}
	break;
	case LOGIC_TO_CENTER_ROOM_AUTO_JOIN:	//自动加入
	{
		AutoJoin(package);
	}
	break;
	default:
		break;
	}
}

//房间列表
void CenterRoomModule::RoomList(RECV_PACKAGE &package)
{
	LCRoom_List req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_CreateRoom parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	uint32_t dupId = req.dupid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	Room_ListRsp rsp;
	rsp.set_retcode(RET_SUCCESS);
	rsp.set_dup_id(dupId);
	SET_UINT32 roomSet;
	g_GetRoomMgr()->getDupRoom(dupId, roomSet);
	if (roomSet.size() > 0)
	{
		SET_UINT32::const_iterator iter = roomSet.begin();
		for (; iter != roomSet.end(); ++iter)
		{
			uint32_t roomId = (*iter);
			Room *room = g_GetRoomMgr()->getRoom(roomId);
			if (nullptr != room)
			{
				RoomDetailProto *protoDetail = rsp.add_room_lst();
				if (nullptr != protoDetail)
				{
					RoomProto *protoRoom = protoDetail->mutable_room();
					RoomAllMemberProto *protoMember = protoDetail->mutable_member();
					room->getRoomProto(protoRoom);
					room->getAllMemberProto(protoMember);
				}
			}
		}
	}

	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_LIST, &rsp);
}
//创建房间
void CenterRoomModule::CreateRoom(RECV_PACKAGE &package)
{
	LCRoom_CreateRoom req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_CreateRoom parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	uint32_t dupId = req.dupid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	if (req.pwd_size() > 0 && req.pwd_size() != ROOM_MAX_PAWD_LEN)
	{
		LogErrFmtPrint("[center] LCRoom_CreateRoom..req.pwd_size() > 0 && req.pwd_size() != ROOM_MAX_PAWD_LEN..cid:%lu,isize:%d,dupid:%u ", charId, req.pwd_size(), dupId);
		return;
	}
	Room_CreateRsp createRsp;
	int32_t ret = g_GetRoomMgr()->canCreateRoom(charId);
	if (RET_SUCCESS == ret)
	{
		int8_t *pppwd = nullptr;
		int8_t arypwd[ROOM_MAX_PAWD_LEN] = { 0 };
		int32_t isize = req.pwd_size();
		if (isize > 0)
		{
			pppwd = arypwd;
			for (int32_t i = 0; i < ROOM_MAX_PAWD_LEN; ++i)
			{
				arypwd[i] = req.pwd(i);
			}
		}
		Room *room = g_GetRoomMgr()->createRoom(charId, dupId, pppwd);
		if (nullptr != room)
		{
			RoomDetailProto *protoDetail = createRsp.mutable_detail();
			if (nullptr != protoDetail)
			{
				RoomProto *protoRoom = protoDetail->mutable_room();
				RoomAllMemberProto *protoMember = protoDetail->mutable_member();
				room->getRoomProto(protoRoom);
				room->getAllMemberProto(protoMember);
			}
		}
		else
		{
			ret = RET_FAIL;
		}
	}
	createRsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_CREATE, &createRsp);
}
//设置密码
void CenterRoomModule::SetRoomPwd(RECV_PACKAGE &package)
{
	LCRoom_SetPwd req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_SetPwd parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	int32_t itype = req.type();//1 设置，2 取消
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}

	Room_SetPwdRsp setRsp;
	int32_t ret = g_GetRoomMgr()->canSetPwd(charId);
	if (RET_SUCCESS == ret)
	{
		int8_t *ppwd = nullptr;
		int8_t aryPwd[ROOM_MAX_PAWD_LEN] = { 0 };
		if (1 == itype)
		{
			int32_t isize = req.pwd_size();
			if (isize != ROOM_MAX_PAWD_LEN)
			{
				LogErrFmtPrint("[center] LCRoom_SetPwd..isize != ROOM_MAX_PAWD_LEN..cid:%lu,isize:%d ", charId, isize);
				return;
			}			
			ppwd = aryPwd;
			for (int32_t i = 0; i < ROOM_MAX_PAWD_LEN; ++i)
			{
				aryPwd[i] = req.pwd(i);
				setRsp.add_pwd(req.pwd(i));
			}
		}
		uint32_t roomId = g_GetRoomMgr()->getCharRoom(charId);
		Room *room = g_GetRoomMgr()->getRoom(roomId);
		if (nullptr != room)
		{
			room->pwd(ppwd);

			//密码变更，需要通知房员
			Room_NotifyUpdate protoUpdate;
			RoomDetailProto* protoDetial = protoUpdate.mutable_update();
			if (nullptr != protoDetial)
			{
				RoomProto *protoRoom = protoDetial->mutable_room();
				room->getRoomProto(protoRoom);
				g_GetRoomMgr()->broadRoom(roomId, EMODULE_ID_ROOM, LOGIC_TO_CLIENT_ROOM_NOTIFY_UPDATE, &protoUpdate);
			}
		}
		else
		{
			ret = RET_FAIL;
		}
	}
	setRsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_SET_PWD, &setRsp);
}
//加入房间
void CenterRoomModule::JoinRoom(RECV_PACKAGE &package)
{
	LCRoom_Join req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_Join parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	uint32_t roomId = req.roomid();
	uint32_t dupId = req.dup_id();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	Room_JoinRsp joinRsp;
	int8_t *ppwd = nullptr;
	int8_t arypwd[ROOM_MAX_PAWD_LEN] = { 0 };
	int32_t ret = RET_SUCCESS;
	if (req.pwd_size() > 0)
	{
		if (req.pwd_size() != ROOM_MAX_PAWD_LEN)
		{
			LogErrFmtPrint("[center] LCRoom_Join req.pwd_size() != ROOM_MAX_PAWD_LEN...charId:%lu,reqsize:%d ", charId, req.pwd_size());
			return;
		}
		ppwd = arypwd;
		for (int32_t i = 0; i < ROOM_MAX_PAWD_LEN; ++i)
		{
			arypwd[i] = req.pwd(i);
		}
	}
	

	//
	ret = g_GetRoomMgr()->canJoinRoom(charId, roomId,dupId, ppwd);
	if (RET_SUCCESS == ret)
	{
		Room *room = g_GetRoomMgr()->joinRoom(charId, roomId, ERoomMemberType_Member);
		if (nullptr != room)
		{
			RoomDetailProto *protoDetail = joinRsp.mutable_detail();
			if (nullptr != protoDetail)
			{
				RoomProto *protoRoom = protoDetail->mutable_room();
				RoomAllMemberProto *protoMember = protoDetail->mutable_member();
				room->getRoomProto(protoRoom);
				room->getAllMemberProto(protoMember);
			}
		}
		else
		{
			ret = RET_FAIL;
		}
	}
	joinRsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_JOIN, &joinRsp);

}
//邀请好友
void CenterRoomModule::InviteFriend(RECV_PACKAGE &package)
{
	LCRoom_InviteFriend req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_InviteFriend parse failed....");
		return;
	}
	CharIDType charId = req.charid();
	CharIDType frdCid = req.friend_cid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}

	int32_t ret = RET_SUCCESS;
	ActiveCharacter *pFrdOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(frdCid);
	if (nullptr == pFrdOnline)
	{
		ret = RET_ROOM_FRIEND_NOT_ONLINE;
	}
	else
	{
		uint32_t roomId = g_GetRoomMgr()->getCharRoom(charId);
		Room *room = g_GetRoomMgr()->getRoom(roomId);
		if (nullptr == room)
		{
			ret = RET_ROOM_NOT_EXIST;
		}
		else
		{
			ret = g_GetRoomMgr()->canInviteRoom(charId, roomId, frdCid);
			if (RET_SUCCESS == ret)
			{
				//通知对方，房主邀请你加入房间
				Room_NotifyRecvInvite notify;
				RoomProto *protoRoom = notify.mutable_room();
				RoomMemberProto *protoMember = notify.mutable_owner();
				room->getRoomProto(protoRoom);
				room->getMemberProto(protoMember, room->roomOwner());
				g_GetCenterService()->SendDataToClient(frdCid, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_NOTIFY_INVITE, &notify);
			}
		}
	}	
	
	
	Room_InviteRsp rsp;
	rsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_INVITE_FRIEND, &rsp);
}
//回复邀请
void CenterRoomModule::ReplyInvite( RECV_PACKAGE &package)
{
	LCRoom_ReplyInvite req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_ReplyInvite parse failed...");
		return;
	}
	int32_t reply = req.reply(); // 1 同意，2 拒绝
	uint32_t roomId = req.room_id();
	CharIDType charId = req.charid();
	uint32_t dupId = req.dup_id();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetActiveCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	OfflineCharacterData *pOfflineData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOfflineData)
	{
		LogErrFmtPrint("[center] CenterRoomModule::ReplyInvite...nullptr == pOfflineData charid:%llu ", charId);
		return;
	}
	Room_ReplyInviteRsp replyRsp;
	int32_t ret = RET_SUCCESS;
	if (1 == reply)
	{
		int8_t *ppwd = nullptr;
		int8_t arypwd[ROOM_MAX_PAWD_LEN] = { 0 };
		int32_t isize = req.pwd_size();
		if (isize > 0)
		{
			if (isize != ROOM_MAX_PAWD_LEN)
			{
				LogErrFmtPrint("[center] CenterRoomModule::ReplyInvite...isize != ROOM_MAX_PAWD_LEN...cid:%lu,isize:%d ",charId,isize);
				return;
			}
			ppwd = arypwd;
			for (int32_t i = 0; i < ROOM_MAX_PAWD_LEN; ++i)
			{
				arypwd[i] = req.pwd(i);
			}
		}

		ret = g_GetRoomMgr()->canJoinRoom(charId, roomId, dupId, ppwd);
		if (RET_SUCCESS == ret)
		{
			Room *room = g_GetRoomMgr()->joinRoom(charId, roomId, ERoomMemberType_Member);
			if (nullptr != room)
			{
				RoomDetailProto *protoDetail = replyRsp.mutable_detail();
				if (nullptr != protoDetail)
				{
					RoomProto *protoRoom = protoDetail->mutable_room();
					RoomAllMemberProto *protoMember = protoDetail->mutable_member();
					room->getRoomProto(protoRoom);
					room->getAllMemberProto(protoMember);
				}
			}
			else
			{
				ret = RET_FAIL;
				RoomDetailProto *protoDetail = replyRsp.mutable_detail();
				if (nullptr != protoDetail)
				{
					//这里不能取房间信息，因为有可能房间不存在了，但是前端还是需要房间ID和副本ID
					RoomProto *protoRoom = protoDetail->mutable_room();
					protoRoom->set_room_id(roomId);
					protoRoom->set_dup_id(dupId);
				}
			}
		}

	}
	else
	{
		Room *room = g_GetRoomMgr()->getRoom(roomId);
		if (nullptr == room)
		{
			ret = RET_ROOM_NOT_EXIST;
		}
		else if (g_GetRelationMgr()->IsFriendRelation(charId,room->roomOwner()))
		{
			//拒绝邀请，如果和房主是好友关系，才会通知房主
			Room_NotifyRefuse notify;
			notify.set_name(pOfflineData->GetCharName());
			g_GetCenterService()->SendDataToClient(room->roomOwner(), (uint16_t)EMODULE_ID_ROOM, LOGIC_TO_CLIENT_ROOM_NOTIFY_REFUSE, &notify);
		}
		if (RET_SUCCESS == ret)
		{
			g_GetRoomMgr()->refuseJoin(charId, roomId);
		}
		RoomDetailProto *protoDetail = replyRsp.mutable_detail();
		if (nullptr != protoDetail)
		{
			//这里不能取房间信息，因为有可能房间不存在了，但是前端还是需要房间ID和副本ID
			RoomProto *protoRoom = protoDetail->mutable_room();
			protoRoom->set_room_id(roomId);
			protoRoom->set_dup_id(dupId);
		}
	}
	replyRsp.set_retcode(ret);
	replyRsp.set_reply(reply);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_INVITE_REPLY, &replyRsp);

}
//请离房间
void CenterRoomModule::KickRoom(RECV_PACKAGE &package)
{
	LCRoom_KickRoom req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_KickRoom parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	CharIDType kickCharId = req.cid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetActiveCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	if (charId == kickCharId)
	{
		return;
	}
	int32_t ret = RET_SUCCESS;
	ret = g_GetRoomMgr()->canKickRoom(charId, kickCharId);
	if (RET_SUCCESS == ret)
	{
		Room *room = g_GetRoomMgr()->kickRoom(charId, kickCharId);
		if (nullptr == room)
		{	
			ret = RET_FAIL;
		}
	}
	Room_KickRsp rsp;
	rsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_KICK, &rsp);
}
//离开房间
void CenterRoomModule::LeaveRoom( RECV_PACKAGE &package)
{
	LCRoom_LeaveRoom req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_LeaveRoom parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetActiveCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	int32_t ret = RET_SUCCESS;
	ret = g_GetRoomMgr()->canLeaveRoom(charId);
	if (RET_SUCCESS == ret)
	{
		if (!g_GetRoomMgr()->leaveRoom(charId))
		{
			ret = RET_FAIL;
		}
	}
	Room_LeaveRsp rsp;
	rsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_LEAVE, &rsp);

}
//自动加入
void CenterRoomModule::AutoJoin(RECV_PACKAGE &package)
{
	LCRoom_AutoJoin req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] LCRoom_AutoJoin parse failed...");
		return;
	}
	CharIDType charId = req.charid();
	uint32_t dupId = req.dupid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetActiveCharacter(charId);
	if (nullptr == pOnline || pOnline->GetDisconnectFlag())
	{
		return;
	}
	if (g_GetRoomMgr()->isAutoJoinCd(charId))
	{
		//cd中
		return;
	}
	g_GetRoomMgr()->updateAutoJoinCd(charId);
	Room_AutoJoinRsp rsp;
	int32_t ret = RET_SUCCESS;
	Room *room = g_GetRoomMgr()->getRandRoom(charId, dupId);
	if (nullptr == room)
	{
		//没有可加入的房间
		ret = RET_ROOM_NO_ROOM_CAN_JOIN;
	}
	else
	{
		ret = g_GetRoomMgr()->canJoinRoom(charId, room->roomId(),dupId);
		if (RET_SUCCESS == ret)
		{
			Room *roomJoin = g_GetRoomMgr()->joinRoom(charId, room->roomId(), ERoomMemberType_Member);
			if (nullptr != roomJoin)
			{
				RoomDetailProto *protoDetail = rsp.mutable_detail();
				if (nullptr != protoDetail)
				{
					RoomProto *protoRoom = protoDetail->mutable_room();
					RoomAllMemberProto *protoMember = protoDetail->mutable_member();
					roomJoin->getRoomProto(protoRoom);
					roomJoin->getAllMemberProto(protoMember);
				}
			}
			else
			{
				ret = RET_FAIL;
			}
		}
	}

	rsp.set_retcode(ret);
	g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_ROOM, (uint16_t)LOGIC_TO_CLIENT_ROOM_AUTO_JOIN, &rsp);


}
